package com.wsoft.bpm.component;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;

import java.util.List;

/**
 * 节点动态跳转
 *
 * @Author zhonglj
 * @Date 2024-10-08 11:13
 */
@Log4j2
@AllArgsConstructor
public class DynamicJumpCmd implements Command<Boolean> {

    /**
     * 流程实例id
     */
    private String processInstanceId;

    /**
     * 从哪个节点
     */
    private String fromActivityId;

    /**
     * 跳转到那个节点
     */
    private String toActivityId;


    @Override
    public Boolean execute(CommandContext commandContext) {
        log.info("node jump: processInstanceId={}, fromActivityId={}, toActivityId={}", processInstanceId, fromActivityId, toActivityId);
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        ExecutionEntity executionEntity = executionEntityManager.findById(processInstanceId);
        if (executionEntity == null) {
            log.error("processInstanceId is not exist");
            return false;
        }

        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(executionEntity.getProcessDefinitionId());
        FlowElement fromFlowElement = bpmnModel.getFlowElement(fromActivityId);
        if (fromFlowElement == null) {
            log.error("fromActivityId is not exist");
            return false;
        }

        FlowElement toFlowElement = bpmnModel.getFlowElement(toActivityId);
        if (toFlowElement == null) {
            log.error("toActivityId is not exist");
            return false;
        }

        // 找出子执行实例fromActivityId，并删除该执行实例
        List<ExecutionEntity> childList = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId);
        ExecutionEntity currentChildExecutionEntity = null;
        for (ExecutionEntity child : childList) {
            if (child.getCurrentActivityId().equals(fromActivityId)) {
                currentChildExecutionEntity = child;
                break;
            }
        }
        executionEntityManager.deleteExecutionAndRelatedData(currentChildExecutionEntity, "任务动态跳转");

        // 创建新的执行实例，并绑定到toActivityId
        ExecutionEntity childExecution = executionEntityManager.createChildExecution(executionEntity);
        childExecution.setCurrentFlowElement(toFlowElement);

        // 执行流程操作
        Context.getAgenda().planContinueProcessOperation(childExecution);
        return true;
    }
}

